package com.ruoyi.gis.utils;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.sun.jna.platform.RasterRangesUtils;
import it.geosolutions.geoserver.rest.GeoServerRESTPublisher;
import it.geosolutions.imageioimpl.plugins.tiff.gdal.GDALMetadataParser;
import it.geosolutions.jaiext.range.NoDataContainer;
import org.geotools.coverage.Category;
import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.grid.GridCoordinates2D;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.GridFormatFinder;
import org.geotools.coverage.processing.CoverageProcessor;
import org.geotools.coverage.processing.operation.ZonalStatistics;
import org.geotools.coverage.util.CoverageUtilities;
import org.geotools.data.DataUtilities;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.gce.geotiff.GeoTiffFormat;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.gce.image.WorldImageFormat;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.map.RasterLayer;
import org.geotools.referencing.CRS;
import org.geotools.referencing.NamedIdentifier;
import org.geotools.referencing.operation.matrix.XAffineTransform;
import org.geotools.styling.*;
import org.geotools.util.NumberRange;
import org.geotools.util.factory.Hints;
import org.opengis.coverage.Coverage;
import org.opengis.coverage.SampleDimensionType;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.filter.FilterFactory2;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Envelope;
import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.operation.TransformException;
import org.opengis.style.ContrastMethod;

import javax.measure.Unit;
import javax.media.jai.ImageLayout;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.io.File;
import java.io.IOException;
import java.util.List;

public class TifUtils {

    public static void readInfo(String TIF_PATH) throws IOException {

        GeoTiffReader geoTiffReader = new GeoTiffReader(TIF_PATH);
        //获取到其bbox
        GeneralEnvelope envelope = geoTiffReader.getOriginalEnvelope();
        //获取到投影信息
        CoordinateReferenceSystem crs = geoTiffReader.getCoordinateReferenceSystem();
        //获取tiff的gridrange(网格范围，按像素说就是像素数量，也就是是tiff的rectangle)
        GridEnvelope gridEnvelope = geoTiffReader.getOriginalGridRange();
        //获取其图像相关信息
        ImageLayout imageLayout = geoTiffReader.getImageLayout();
        //获取colormodel
        ColorModel colorModel = imageLayout.getColorModel(null);
        //查看其通道数量
        int num = colorModel.getNumComponents();
        //是否支持透明
        boolean isAlpha = colorModel.hasAlpha();
        //获取颜色空间
        ColorSpace clorspace = colorModel.getColorSpace();
        //获取samplemodel
        SampleModel sampleModel = imageLayout.getSampleModel(null);
        //数据类型
        int datatype = sampleModel.getDataType();
        geoTiffReader.dispose();
    }


//    private static int asysNdvi(long id,String geojson,String tifPath,float minNdvi,float maxNdvi){
//        int state=0;
//        String suff="_"+id+".tif";
//        String outPath=tifPath.replace(".tif",suff);
//        Dataset ds=gdal.Open(tifPath);
//        Vector vector=new Vector();
//        vector.add("-cutline");
//        vector.add(geojson);
//        vector.add("-crop_to_cutline");
//        //裁剪数据集
//        Dataset out = gdal.Warp(outPath,new Dataset[]{ds},new WarpOptions(vector));
//        if (out != null){
//            //获取波段
//            Band band=out.GetRasterBand(1);
//            int width=band.getXSize();
//            int height=band.getYSize();
//
//            float[] data=new float[width*height];
//
//            //获取波段值
//            band.ReadRaster(0,0,width,height,data);
//            int num=0,good=0,bad=0,normal=0;
//            //分析波段
//            for(int i=0;i<data.length;i++) {
//                if(data[i]!=0.0&& !ObjectUtil.equals(data[i],Float.NaN)) {
//                    if(data[i]>=maxNdvi){
//                        good++;
//                    } else if(data[i]<minNdvi){
//                        bad++;
//                    }else{
//                        normal++;
//                    }
//                    num++;
//                }
//            }
//            float goodRate=(float) good/num;
//            float badRate=(float)bad/num;
//            float normalRate=(float)normal/num;
//            if(badRate>0.2){
//                state=0;
//            }else if(goodRate>0.2){
//                state=2;
//            }else{
//                state=1;
//            }
//            out.delete();
//            gdal.GetDriverByName("GTiff").Delete(outPath);
//            System.out.println("成功！");
//        }
//        return state;
//    }

    public static void readTifInfo(String rasterFile) throws IOException, TransformException {
        AbstractGridFormat format = GridFormatFinder.findFormat(rasterFile);
        // this is a bit hacky but does make more geotiffs work
        Hints hints = new Hints();
        AbstractGridCoverage2DReader reader = null;
        GridCoverage2D cov = null;
        if (format instanceof GeoTiffFormat) {
            hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
//            reader = format.getReader(new File(rasterFile), hints);
//            cov = reader.read(null);
        }else if(format instanceof WorldImageFormat){
//            reader = new WorldImageReader(new File(rasterFile),hints);
//            cov = reader.read(null);
        }
        reader = format.getReader(new File(rasterFile), hints);
        cov = reader.read(null);
        Envelope envelope = cov.getEnvelope();
        CoordinateReferenceSystem crs = cov.getCoordinateReferenceSystem();
        SingleCRS horizontalCRS = CRS.getHorizontalCRS(crs);
        if(horizontalCRS==null){
            horizontalCRS = CRS.getVerticalCRS(crs);
        }
        String crsStr = GeoServerRESTPublisher.DEFAULT_CRS;
        if(horizontalCRS!=null&&horizontalCRS.getIdentifiers()!=null
                &&horizontalCRS.getIdentifiers().size()>0){
            Object o = horizontalCRS.getIdentifiers().toArray()[0];
            crsStr = ((NamedIdentifier) o).toString();
        }
//        shpInfo.put("crsStr",crsStr);
//        shpInfo.put("crs",crs.toString());

        DirectPosition lowerCorner = envelope.getLowerCorner();
        double[] westSouth = lowerCorner.getCoordinate();
        DirectPosition upperCorner = envelope.getUpperCorner();
        double[] eastNorth = upperCorner.getCoordinate();

        GridGeometry2D gridGeometry = cov.getGridGeometry();
        GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
        int height = gridRange.height;
        int width = gridRange.width;

        AffineTransform gridToCRS = (AffineTransform) gridGeometry.getGridToCRS();
        double xRes = XAffineTransform.getScaleX0(gridToCRS);
        double yRes = XAffineTransform.getScaleY0(gridToCRS);
//        gridToCRS.getTranslateX();
        //起始点
        double translateX = gridToCRS.getTranslateX();
        double translateY = gridToCRS.getTranslateY();
//        GeoTiffIIOMetadataDecoder decoder = new GeoTiffIIOMetadataDecoder(cov.getMetadata());
//        String crs = decoder.getCRSDescription();
//        double pixelSizeX = decoder.getModelPixelScaleX();
//        double pixelSizeY = decoder.getModelPixelScaleY();

//        Statistics stats = cov.getProperty("statistics").getValue();
//        double min = stats.getMinValue();
//        double max = stats.getMaxValue();
//        // 获取NoData值
//        double[] noDataValues = cov.getSampleDimension(0).getNoDataValues();
        // 获取像素值范围
        Raster data = cov.getRenderedImage().getData();
//        double[] minMaxValues = cov.getRenderedImage().getData().getMinMaxValue();
//        double minValue = minMaxValues[0];
//        double maxValue = minMaxValues[1];
//        // 获取NoData值
//        double noDataValue = cov.getSampleDimension(0).getNoDataValue();

//        envelopeParams.put(NORTH, eastNorth[1]);
//        envelopeParams.put(SOUTH, westSouth[1]);
//        envelopeParams.put(WEST, westSouth[0]);
//        envelopeParams.put(EAST, eastNorth[0]);
//        envelopeParams.put(XRES, xRes);
//        envelopeParams.put(YRES, yRes);
//        envelopeParams.put(ROWS, (double) height);
//        envelopeParams.put(COLS, (double) width);
        int numBands = cov.getNumSampleDimensions();
        //获取tiff的gridrange(网格范围，按像素说就是像素数量，也就是是tiff的rectangle)
        GridEnvelope gridEnvelope = reader.getOriginalGridRange();
        //获取其图像相关信息
        ImageLayout imageLayout = reader.getImageLayout();
        //获取colormodel
        ColorModel colorModel = imageLayout.getColorModel(null);
        //查看其通道数量
        int num = colorModel.getNumComponents();
        //是否支持透明
        boolean isAlpha = colorModel.hasAlpha();
        //获取颜色空间
        ColorSpace clorspace = colorModel.getColorSpace();
        //获取samplemodel
        SampleModel sampleModel = imageLayout.getSampleModel(null);
        // 获取图像范围
        RenderedImage image = cov.getRenderedImage();
        Raster raster = image.getData();
        //raster.getPixel()
        //raster.getSample()
        SampleModel sampleModel2 = raster.getSampleModel();
        // 获取栅格数据集的几何属性
        GridGeometry2D geometry = cov.getGridGeometry();
        Envelope2D envelope2D = cov.getEnvelope2D();
        NoDataContainer noDataProperty = CoverageUtilities.getNoDataProperty(cov);
        //遍历所有像素
//        for (int i = 0; i < width; i++) {
//            for (int j = 0; j < height; j++) {
//                double pixelValue = image.getData().getSampleDouble(i, j, 0);
//                if (pixelValue > 0) {
//                    GridCoordinates2D gridPos = new GridCoordinates2D(i, j);
//                    // 将像素点转换为坐标
//                    DirectPosition worldPos = geometry.gridToWorld(gridPos);
//                    double longitude = worldPos.getCoordinate()[1];
//                    double latitude = worldPos.getCoordinate()[0];
//                    String coordinate = "point(" + longitude + "," + latitude + ")";
//                    System.out.println(coordinate);
//                    System.out.println("像素点 (" + i + ", " + j + ") 的值： " + pixelValue + "    坐标为:" + worldPos.getCoordinate()[0] + "，" + worldPos.getCoordinate()[1]);
//                }
//            }
//        }
//        double[] minValues = cov.getRenderedImage().getData()
//                .getPixelMin(0, 0, (int)cov.getRenderedImage().getWidth(), (int)cov.getRenderedImage().getHeight(), (double[])null);
//        double[] maxValues = cov.getRenderedImage().getData().
//                getPixelMax(0, 0, (int)cov.getRenderedImage().getWidth(), (int)cov.getRenderedImage().getHeight(), (double[])null);
//        raster.getp
        System.out.println("图片宽:" + width);
        System.out.println("图片高:" + height);
        //geotools 24.2  计算栅格数据集中像素值最小值和最大值
        CoverageProcessor processor = CoverageProcessor.getInstance();
//        ParameterValueGroup params = processor.getOperation("MinMax").getParameters();
//        params.parameter("Source").setValue(cov);
//        Coverage result =  processor.doOperation(params);
//        double minValue = (double) result.getProperty("minimum").getValue();
//        double maxValue = (double) result.getProperty("maximum").getValue();

        // 2. 计算像元值范围
        double[] minValues = new double[cov.getNumSampleDimensions()];
        double[] maxValues = new double[cov.getNumSampleDimensions()];
//        cov.getRenderedImage().getData().computeRasterMinMax(minValues, maxValues);

//        ParameterValueGroup parameters = processor.getOperation("MaxFilter").getParameters();
//        parameters.parameter("Source").setValue(cov);
//        Coverage result =  processor.doOperation(parameters);
//        RasterRangesUtils.RangesOutput out = new RasterRangesUtils.RangesOutput() {
//            @Override
//            public boolean outputRange(int i, int i1, int i2, int i3) {
//                return false;
//            }
//        };
//        RasterRangesUtils.outputOccupiedRanges(raster, out);
        //ZonalStatistics
//        ZonalStatistics
        //数据类型
        int datatype = sampleModel.getDataType();
        JSONArray bands = new JSONArray();
        for (int i = 0; i < numBands; i++) {
            JSONObject band = new JSONObject();
            GridSampleDimension dim = cov.getSampleDimension(i);
            String bandName = dim.getDescription().toString();
            double[] noDataValues = dim.getNoDataValues();
            //geotools 计算栅格数据集中像素值最小值和最大值
            double maximumValue = dim.getMaximumValue();
            double minimumValue = dim.getMinimumValue();

            //DataUtilities.computeRasterMinMax
//            RasterRangesUtils.outputOccupiedRanges()
//            double minValue = Double.MAX_VALUE;
//            double maxValue = Double.MIN_VALUE;
//            double minimum1 = envelope.getMinimum(i);
//            double maximum1 = envelope.getMaximum(i);
//            double min = (double) cov.evaluate(envelope.getMinimum(i), envelope.getMinimum(i), i);
//            double max = (double) cov.evaluate(envelope.getMaximum(i), envelope.getMaximum(i), i);


            Unit<?> units = dim.getUnits();//维度的单位
            SampleDimensionType sampleDimensionType = dim.getSampleDimensionType();
            ColorModel bandcolorModel = dim.getColorModel();
            int pixelSize = bandcolorModel.getPixelSize();
            band.put("noDataValues",noDataValues!=null&&noDataValues.length>0?noDataValues[0]:null);
            band.put("maximumValue",maximumValue);
            band.put("minimumValue",minimumValue);
            band.put("pixelSize",pixelSize);
            band.put("description",dim.getDescription()!=null? bandName :"");
//            band.put("");
            JSONArray cates = new JSONArray();
            List<Category> categories = dim.getCategories();
            if(categories!=null){
                for(Category category:categories) {
                    JSONObject cate = new JSONObject();
                    cate.put("name",category.getName()!=null?category.getName().toString():"");
                    NumberRange<? extends Number> range = category.getRange();
                    if(range!=null){
                        double maximum = range.getMaximum();
                        double minimum = range.getMinimum();
                        cate.put("maximum",maximum);
                        cate.put("minimum",minimum);
                    }
//                    Category.NODATA.getName().equals(category.getName())
                    cates.add(cate);
                }
            }
            band.put("categories",cates);
            //这里依次输出 RED_BAND  GREEN_BANK BLUE_BANK
            System.out.println(bandName);
            bands.add(band);
        }
        //nodata https://blog.csdn.net/qq_16428395/article/details/127305295
        reader.dispose();
        reader = null;
    }
    private static Style createGreyscaleStyle(int band) {
        StyleFactory sf = CommonFactoryFinder.getStyleFactory();
        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
        ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);
        SelectedChannelType sct = sf.createSelectedChannelType(String.valueOf(band), ce);
        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
        ChannelSelection sel = sf.channelSelection(sct);
        sym.setChannelSelection(sel);
        return SLD.wrapSymbolizers(sym);
    }
    private Style createRGBStyle(AbstractGridCoverage2DReader reader) {
        GridCoverage2D cov = null;
        try {
            cov = reader.read(null);
        } catch (IOException giveUp) {
            throw new RuntimeException(giveUp);
        }
        //我们需要至少三个波段的样式
        int numBands = cov.getNumSampleDimensions();
        if (numBands < 3) {
            return null;
        }
        //获取各个波段的名称
        String[] sampleDimensionNames = new String[numBands];
        for (int i = 0; i < numBands; i++) {
            GridSampleDimension dim = cov.getSampleDimension(i);
            sampleDimensionNames[i] = dim.getDescription().toString();
        }
        final int RED = 0, GREEN = 1, BLUE = 2;
        int[] channelNum = {-1, -1, -1};
        for (int i = 0; i < numBands; i++) {
            String name = sampleDimensionNames[i].toLowerCase();
            if (name != null) {
                if (name.matches("red.*")) {
                    channelNum[RED] = i + 1;
                } else if (name.matches("green.*")) {
                    channelNum[GREEN] = i + 1;
                } else if (name.matches("blue.*")) {
                    channelNum[BLUE] = i + 1;
                }
            }
        }
        if (channelNum[RED] < 0 || channelNum[GREEN] < 0 || channelNum[BLUE] < 0) {
            channelNum[RED] = 1;
            channelNum[GREEN] = 2;
            channelNum[BLUE] = 3;
        }
        StyleFactory sf = CommonFactoryFinder.getStyleFactory();
        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
        //我们使用selected通道创建RasterSymbolizer样式
        SelectedChannelType[] sct = new SelectedChannelType[cov.getNumSampleDimensions()];
        ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);
        for (int i = 0; i < 3; i++) {
            sct[i] = sf.createSelectedChannelType(String.valueOf(channelNum[i]), ce);
        }
        RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
        ChannelSelection sel = sf.channelSelection(sct[RED], sct[GREEN], sct[BLUE]);
        sym.setChannelSelection(sel);
        return SLD.wrapSymbolizers(sym);
    }



    public static void main(String[] args) throws IOException, TransformException {
//        System.setProperty("javax.xml.parsers.DocumentBuilderFactory",
//                "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
//        readTifInfo("D:\\work\\platform\\argcsystem\\deploy\\geoserver\\data\\tif\\1734774886201114624\\小麦.tif");
//        readTifInfo("D:\\work\\数据\\月鑫深度学习测试图片\\建筑物提取\\0_13_1.tif");
//        readTifInfo("D:\\work\\数据\\刘园增城市数据\\2021年增城市土壤有机质\\2021年增城市土壤有机质.tif");
//        Style greyscaleStyle = createGreyscaleStyle(1);
//        readTifInfo("D:\\work\\赤红壤\\数据\\刘园增城市数据\\2020年增城市作物轮作系统\\2020年增城市作物轮作系统.tif");
//        readTifInfo("D:\\work\\赤红壤\\广东省耕地质量评价数据\\2018耕地质量等级10等\\2018耕地质量等级10等.tif");
//        readTifInfo("D:\\work\\赤红壤\\广东省耕地质量评价数据\\2018耕地质量分数\\2018耕地质量分数.tif");
        readTifInfo("D:\\work\\赤红壤\\数据\\刘园增城市数据\\2021年增城市土壤pH值\\2021年增城市土壤pH值.tif");
        int a = 0;
    }

}
